package cloud.lysky.java.on.concurrent.lock.readwritelock;

/**
 * @author luoly
 * @describe 实现一个读写锁
 * @date 2023-04-30 21:20
 **/
// 读写锁设计思路：
// 1. 读锁和写锁都是可重入的
// 2. 读锁是共享锁，写锁是独占锁
// 3. 读锁和写锁是互斥的
// 4. 写锁优先级高于读锁
// 5. 支持锁降级，不支持锁升级
public class MyReadWriteLock {
    private int readers = 0; // 读锁的个数
    private boolean isWrite = false; // 是否有写锁
    private final Object lock = new Object(); // 用于同步的锁对象

    // 获取读锁
    public void readLock(){
        synchronized (lock){
            while (isWrite){ // 如果有写锁，则等待
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            readers++; // 读锁个数增加
        }
    }
    // 释放读锁
    public void readUnlock(){
        synchronized (lock){
            readers--; // 读锁个数减少
            if (readers == 0){ // 如果读锁个数为0，则唤醒所有等待的线程
                lock.notifyAll();
            }
        }
    }

    // 获取写锁
    public void writeLock(){
        synchronized (lock){
            while (isWrite || readers > 0){ // 如果有写锁或者有读锁，则等待
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            isWrite = true; // 获取写锁
        }
    }
    // 释放写锁
    public void writeUnlock(){
        synchronized (lock){
            isWrite = false; // 释放写锁
            lock.notifyAll(); // 唤醒所有等待的线程
        }
    }
}
